# -*- coding:utf-8 -*-

import time
import traceback

from server import mysql, cache
from server.frok import bellMode, heart
from server.util import sqlBuild, stringUtil


class taskManger(object):
    reids_test = cache.re()

    def __init__(self):
        self.db, self.conn = mysql.DBService(), cache.re().redis
        self.bellMode = bellMode.bellMode(self.db, self.conn)
        self.finish_task, self.execute_task, self.fault_task = [], [], []

    def finished(self):  # 已完成的任务
        if not self.finish_task:
            return
        in_head = sqlBuild.sqlDict["insert_task"]
        in_groove = "('%s',1, %s, CURRENT_TIMESTAMP)"  # 命令，状态(完成)， 执行次数， 更新时间
        sql = stringUtil.build_insert_sql(inHead=in_head, inGroove=in_groove, data=self.finish_task)
        self.db.insert(sql)  # 插入完成任务


    def faulted(self):  # 故障处理
        if not self.fault_task:
            return
        lcId_arr = set()
        for each in self.fault_task:
            arr = each[0].split(",")
            lcId = arr[2]
            lcId_arr.add(lcId)

            data = "警告：路灯[%s]，失去反应，请及时处理！" % lcId
            self.re.publish('faultMessage', data)

        # 更新灯端表sql
        updateLampClientSql = sqlBuild.sqlDict["update_lampClient_fault"] % stringUtil.arr_to_sqlStr(lcId_arr)

        fault_head = sqlBuild.sqlDict["insert_fault"]
        fault_groove = "('%s', '1')" # 目标设备ID, 设备类型, 故障类型, 更新时间
        # 插入故障表语句
        insert_fault_sql = stringUtil.build_insert_sql(inHead=fault_head, inGroove=fault_groove, data=lcId_arr)

        in_head = sqlBuild.sqlDict["insert_task"]
        in_groove = "('%s',2, %s, CURRENT_TIMESTAMP)"  # 命令，状态(故障)， 执行次数， 更新时间
        insert_task_sql = stringUtil.build_insert_sql(inHead=in_head, inGroove=in_groove, data=self.fault_task)

        self.db.update(insert_task_sql, updateLampClientSql, insert_fault_sql)  # 需要一次性更新任务表/灯端表/故障表


    def executed(self):  # 继续执行
        if not self.execute_task:
            return
        self.bellMode.messageHandler(self.execute_task)

    def taskHandler(self, tasks):  # 分配任务
        lc_list = {}
        for task in tasks:
            # 命令、执行次数
            string, count = task[0], int(task[1])
            task = (string, count)
            if count > 3:  # 如果执行次数超过三次，归为故障
                self.fault_task.append(task)
                continue
            # if count >= 3:  #  TODO 测试用，展会后记得删除
            #     self.finish_task.append(task)
            #     continue
            if count == 0:  # 未执行任务
                self.execute_task.append(task)
                continue

            arr = string.split(",")
            com = arr[1]  # 命令
            if com == "lnon" or com == "lnof":  # 如果是单发任务则需要进行二次判断
                lcId = arr[2]  # 灯端ID
                lc_list[lcId] = (task, 1 if com == "lnon" else 0)
            else:
                self.finish_task.append(task)
        self.doSearch(lc_list)

    def doSearch(self, lc_list):
        if not lc_list:
            return
        into = stringUtil.arr_to_sqlStr(lc_list.keys())
        sql = sqlBuild.sqlDict["select_lampClient_state"] % into
        other = self.db.select(sql)  # 路灯当前状态
        for each in other:
            state, lcId = each["state"], each["lcId"]  # 路灯当前状态
            task, need_state = lc_list[lcId]  # 任务，任务需求状态

            if need_state == int(state):
                self.finish_task.append(task)
            else:
                self.execute_task.append(task)

    @reids_test.re_batch
    def get_tasks(self, keys, pipe=None):
        for key in keys:
            pipe.zrange(key, 0, -1, withscores=True)

    def handler(self):
        self.finish_task, self.execute_task, self.fault_task = [], [], []
        keys = self.conn.keys("SSBS*")
        ss_tasks = self.get_tasks(keys)
        tasks = self.conn.zrange("material", 0, -1, withscores=True)  # 从队列中检索
        for each in ss_tasks:
            tasks = tasks + each
        self.conn.delete("material")
        # tasks = self.db.select(sqlBuild.sqlDict["select_task_undown"])  # 检索所有未完成的任务
        if tasks:
            self.taskHandler(tasks)
            self.finished()  # 已完成
            self.faulted()  # 故障
            self.executed()  # 继续执行

    def start(self):
        heart.heart_pick().heart()  # 心跳
        self.handler()


def begin(interval):
    manger = taskManger()
    while True:
        try:
            time.sleep(interval)
            manger.start()
        except Exception, e:
            traceback.print_exc()
            print e.message
            return begin(interval)

# begin(30)